#pragma once

#include <iostream>
#include <pthread.h>
#include <string>
#include <cstdlib>

class Thread
{
public:
    // 定义枚举类型
    typedef enum
    {
        NEW = 0,
        RUNNING,
        EXITED
    } ThreadStatus;

    typedef void* (*func_t)(void*); // 函数指针

public:
    //构造
    Thread(int num, func_t func, void* args)
        : _tid(0),
          _status(NEW),
          _func(func),
          _args(args)
    {
        char name[128];
        snprintf(name, sizeof(name), "thread->%d", num);
        _name = name;
    }

    // 获取线程状态
    int status()
    {
        return _status;
    }
    // 获取线程名称
    const std::string &threadname()
    {
        return _name;
    }
    // 获取线程tid：线程运行才返回，否则返回0（打印提示）
    const std::string threadid()
    {
        if (_status == RUNNING)
            return stringID();
        else
            return "0";
    }

    // 线程id转换为16进制，以字符串输出
    const std::string stringID()
    {
        char id[64];
        snprintf(id, sizeof(id), "0x%x", _tid);
        return id;
    }

    // void *runHelper(void* args) //报错，类中实现的成员函数，默认存在this参数
    // {}

    //利用静态成员函数,防止默认参数（this）生成
    static void* runHelper(void* args)
    {
        //调用外部函数
        //_func(); //报错，静态成员函数不能直接调用成员变量/成员函数

        //处理方式：创建线程时，传入Thread对象（this）
        Thread* ts = static_cast<Thread*>(args);//类型转换
        (*ts)(); //函数对象,调用传入的函数

        return nullptr;
    }

    void operator()() //仿函数
    {
        if(_func != nullptr) _func(_args);
    }

    //线程执行
    void run()
    {
        // 创建线程
        // int n = pthread_create(&_tid, nullptr, runHelper, nullptr);
        int n = pthread_create(&_tid, nullptr, runHelper, this);//传入this，Thread本身

        if(n != 0) exit(1);    
        // 更改线程状态
        _status = RUNNING;
    }
    // 等待线程
    void join()
    {
        int n = pthread_join(_tid, nullptr);
        if (n != 0) 
        {
            std::cerr << "main thread join thread " << _name << " error" << std::endl;
            return;
        }
        _status = EXITED;
    }

    ~Thread() {}

private:
    pthread_t _tid;       // 线程id
    std::string _name;    // 线程名
    func_t _func;         // 线程未来要执行的回调函数
    void* _args;           //回调函数的参数
    ThreadStatus _status; // 线程所处的状态
};